﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using ComicIsland.Common;
using ComicIsland.Common.Entities.InterfaceJson;
using ComicIsland.Common.Entities.LocalDatabase;
using ComicIsland.Common.StorageHelper;
using ComicIsland.Common.WebHelper;
using Microsoft.Phone.BackgroundTransfer;

/**
 * 创建时间：2015/1/13 10:40:13
 * 作者：yong.blackcore
 * Email：itblackhole@outlook.com
 * QQ：50404503
 */
namespace ComicIsland.App.Views.CacheManage
{
    public delegate void CacheQueueAssistantStatusChanged(LDBComicChapterImage ldbComicChapterImage);


    public class CacheQueueAssistant
    {
        System.Threading.Mutex mutex = new System.Threading.Mutex(false, "ComicIsland.CacheQueueAssistant");
        public event CacheQueueAssistantStatusChanged OnCacheQueueAssistantStatusChanged;
        public int ComicId { get; private set; }
        public int BookId { get; private set; }
        //
        private bool IsFirstRun = true;
        private bool _isLoadNetData = false;
        //private bool _isRunning = false;
        //private bool _isPause = false;
        //public bool IsRuning
        //{
        //    get { return _isRunning; }
        //    set { _isRunning = value; }
        //}

        //public bool IsLoadNetData
        //{
        //    get { return _isLoadNetData; }
        //    set { _isLoadNetData = value; }
        //}
        //public bool IsPause
        //{
        //    get { return _isPause; }
        //    set { _isPause = value; }
        //}

        /// <summary>
        /// 漫画缓存队列
        /// </summary>
        /// <param name="comicId">漫画ID</param>
        /// <param name="bookId">漫画源站点ID</param>
        public void InitCacheQueue(int comicId, int bookId)
        {
            if (App.CQASingleton.GetIsRunning() || App.CQASingleton.GetIsLoadNetData())
            {
                LogHelper.LogInfo(string.Format("正在运行中：IsRuning={0},IsLoadNetData={1}", App.CQASingleton.GetIsRunning(), App.CQASingleton.GetIsLoadNetData()));
                return;
            }


            LogHelper.LogInfo(comicId + "\t:1.......", this.GetType(), MethodBase.GetCurrentMethod());
            try
            {
                this.mutex.WaitOne();
                this.ComicId = comicId;
                this.BookId = bookId;
                App.CQASingleton.SetIsRunning(true);
                LogHelper.LogInfo(comicId + "\t:2.......", this.GetType(), MethodBase.GetCurrentMethod());
                //有图片地址则直接获取
                var dbComicChapterImage = App.dbContextHelper.GetOneComicChapterImageByDownloadStatus(ContentDownloadStatus.等待中, this.ComicId);
                if (dbComicChapterImage != null)
                {
                    LogHelper.LogInfo(dbComicChapterImage.ComicIdAndBookIdAndPartId + "\t:3.......", this.GetType(), MethodBase.GetCurrentMethod());
                    this.InsertComicChapterImageToBackgroundTransfer(dbComicChapterImage);
                }
                else
                {
                    //无图片队列，则处理章节队列
                    var dbComicChapter = App.dbContextHelper.GetOneComicChapterByDownloadStatus(ContentDownloadStatus.等待中, this.ComicId);
                    if (dbComicChapter != null)
                    {
                        App.CQASingleton.SetIsLoadNetData(true);
                        LogHelper.LogInfo(dbComicChapter.ComicIdAndBookIdAndPartId + "\t:4.......", this.GetType(), MethodBase.GetCurrentMethod());
                        GetComicChapterImagesByComicChapter(dbComicChapter);
                    }
                    else
                    {
                        LogHelper.LogInfo(string.Concat("漫画ID为:", this.ComicId, " 的章节下载队列处理已经完成，获取其它漫画下载队列！"), this.GetType(), MethodBase.GetCurrentMethod());
                        //this.ComicId对应的章节处理完了，处理别的章节
                        dbComicChapter = App.dbContextHelper.GetOneComicChapterByDownloadStatus(ContentDownloadStatus.等待中);
                        if (dbComicChapter != null)
                        {
                            App.CQASingleton.SetIsLoadNetData(true);
                            this.ComicId = dbComicChapter.ComicId;
                            LogHelper.LogInfo(dbComicChapter.ComicIdAndBookIdAndPartId + "\t:4.......", this.GetType(), MethodBase.GetCurrentMethod());
                            GetComicChapterImagesByComicChapter(dbComicChapter);
                        }
                        else
                        {
                            //没有可处理的数据队列
                            App.CQASingleton.SetIsLoadNetData(false);
                            App.CQASingleton.SetIsRunning(false);
                            LogHelper.LogInfo("所有下载队列处理已经完成，重置参数！", this.GetType(), MethodBase.GetCurrentMethod());

                        }
                    }
                }
            }
            catch (Exception err)
            {
            }
            finally
            {
                this.mutex.ReleaseMutex();
                LogHelper.LogInfo("6......", this.GetType(), MethodBase.GetCurrentMethod());
            }
        }






        #region ******************************下载队列处理******************************
        private void InsertComicChapterImageToBackgroundTransfer(LDBComicChapterImage imageQueue)
        {
            if (BackgroundTransferService.Requests.Count() > 0)
            {
                if (this.IsFirstRun)
                {
                    var item = BackgroundTransferService.Requests.FirstOrDefault<BackgroundTransferRequest>();
                    if (item != null)
                    {
                        this.RemoveTransferRequest(item.RequestId);
                        App.CQASingleton.SetIsRunning(false);
                        this.InitCacheQueue(this.ComicId, this.BookId);
                    }
                }
                return;
            }

            IsFirstRun = false;

            #region 图片文件是否已经存在
            string filePath = string.Concat(KEYS.ComicIslandCacheDirectory, "/", KEYS.CacheImagePrefix, imageQueue.ComicId, "_", imageQueue.PartId, "_", MD5.GetMd5String(imageQueue.ImageUrl));
            LogHelper.LogInfo(filePath, this.GetType(), MethodBase.GetCurrentMethod());
            if (IsolatedStorageHelper.Instance.FileExists(filePath))
            {
                try
                {
                    //更新缓存状态                        
                    App.dbContextHelper.UpdateStatusToComicChapterImage(imageQueue, ContentDownloadStatus.已完成);
                    //激活事件（主要用于更新UI）
                    if (this.OnCacheQueueAssistantStatusChanged != null)
                    {
                        this.OnCacheQueueAssistantStatusChanged(imageQueue);
                        //LogHelper.LogInfo(imageQueue.ComicIdAndBookIdAndPartId + "\t" + imageQueue.ImageUrl,this.GetType (),MethodBase.GetCurrentMethod ());
                    }
                    LogHelper.LogInfo("已经下载了，重新获取队列！", this.GetType(), MethodBase.GetCurrentMethod());
                }
                catch (Exception err)
                {
                    LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
                }
                finally
                {
                    App.CQASingleton.SetIsRunning(false);
                    this.InitCacheQueue(this.ComicId, this.BookId);
                }
                return;
            }
            #endregion 图片文件是否已经存在


            Uri transferUri = new Uri(Uri.EscapeUriString(imageQueue.ImageUrl), UriKind.RelativeOrAbsolute);
            if (BackgroundTransferService.Requests.Any(p => p.RequestUri == transferUri))
            {
                LogHelper.LogInfo("任务已在队列中:\t" + transferUri.ToString());
                var item = BackgroundTransferService.Requests.Where(p => p.RequestUri == transferUri).FirstOrDefault<BackgroundTransferRequest>();
                if (item != null)
                {
                    RemoveTransferRequest(item.RequestId);
                }
                App.CQASingleton.SetIsRunning(false);
                this.InitCacheQueue(this.ComicId, this.BookId);
                return;
            }
            //
            BackgroundTransferRequest transferRequest = new BackgroundTransferRequest(transferUri);
            transferRequest.Method = "GET";
            //防盗链测试
            //imageQueue.ImageUrl = "http://t6.mangafiles.com/Files/Images/6486/115983/imanhua_001.jpg";
            //imageQueue.Referer = "http://www.imanhua.com/comic/6486/list_115983.html";
            if (!string.IsNullOrWhiteSpace(imageQueue.Referer))
            {
                transferRequest.Headers.Add("Referer", imageQueue.Referer);
            }
            Uri downloadUri = new Uri(string.Concat("shared/transfers/", KEYS.CacheImagePrefix, imageQueue.ComicId, "_", imageQueue.PartId, "_", MD5.GetMd5String(imageQueue.ImageUrl)), UriKind.RelativeOrAbsolute);
            transferRequest.DownloadLocation = downloadUri;
            LogHelper.LogInfo(downloadUri.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            //
            transferRequest.Tag = JSONHelper.Serialize<LDBComicChapterImage>(imageQueue);
            transferRequest.TransferPreferences = TransferPreferences.AllowCellularAndBattery;
            try
            {
                transferRequest.TransferProgressChanged += new EventHandler<BackgroundTransferEventArgs>(this.transferRequest_TransferProgressChanged);
                transferRequest.TransferStatusChanged += new EventHandler<BackgroundTransferEventArgs>(this.transferRequest_TransferStatusChanged);
                this.UpdateBackgroundTransfer(transferRequest);
                BackgroundTransferService.Add(transferRequest);
                imageQueue.DownloadStatus = ContentDownloadStatus.下载中.ToString();
                //更新表数据
                App.dbContextHelper.UpdateStatusToComicChapterImage(imageQueue, ContentDownloadStatus.下载中);
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
        }

        /// <summary>
        /// TransferStatus状态属性变更时触发
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void transferRequest_TransferStatusChanged(object sender, BackgroundTransferEventArgs e)
        {
            UpdateBackgroundTransfer(e.Request);
        }

        void transferRequest_TransferProgressChanged(object sender, BackgroundTransferEventArgs e)
        {
            //下载进度变更
            //LogHelper.LogInfo(string.Concat(e.Request.TotalBytesToReceive, "/", e.Request.BytesReceived), this.GetType(), MethodBase.GetCurrentMethod());
        }

        void UpdateBackgroundTransfer(BackgroundTransferRequest transfer)
        {
            try
            {
                switch (transfer.TransferStatus)
                {
                    case TransferStatus.Completed:                        
                        if (transfer.StatusCode == 200 || transfer.StatusCode == 206)
                        {
                            //从队列移除
                            RemoveTransferRequest(transfer.RequestId);
                            //
                            LDBComicChapterImage dbImage = JSONHelper.Deserialize<LDBComicChapterImage>(transfer.Tag);
                            string filefullpath = string.Empty;
                            if (dbImage == null)
                            {
                                LogHelper.LogInfo("队列的下载对象为空！", this.GetType(), MethodBase.GetCurrentMethod());
                                App.CQASingleton.SetIsRunning(false);
                                this.InitCacheQueue(this.ComicId, this.BookId);
                                return;
                            }
                            //
                            string filename = string.Concat(KEYS.ComicIslandCacheDirectory, "/", KEYS.CacheImagePrefix, dbImage.ComicId, "_", dbImage.PartId, "_", MD5.GetMd5String(dbImage.ImageUrl));
                            //LogHelper.LogInfo(filename, this.GetType(), MethodBase.GetCurrentMethod());
                            //将下载的文件移到指定目录下
                            using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
                            {
                                try
                                {
                                    if (!isoStore.FileExists(filename))
                                    {
                                        //isoStore.DeleteFile(filename);
                                        isoStore.MoveFile(transfer.DownloadLocation.OriginalString, filename);
                                    }
                                }
                                catch (Exception err)
                                {
                                    LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
                                }
                            }
                            //更新缓存状态                        
                            App.dbContextHelper.UpdateStatusToComicChapterImage(dbImage, ContentDownloadStatus.已完成);
                            //激活事件（主要用于更新UI）
                            if (this.OnCacheQueueAssistantStatusChanged != null)
                            {
                                this.OnCacheQueueAssistantStatusChanged(dbImage);
                                //LogHelper.LogInfo(dbImage.ComicIdAndBookIdAndPartId + "\t" + dbImage.ImageUrl, this.GetType(), MethodBase.GetCurrentMethod());
                            }
                            //
                            if (BackgroundTransferService.Requests.Count() <= 0)
                            {
                                LogHelper.LogInfo("队列处理完成了，取新队列！", this.GetType(), MethodBase.GetCurrentMethod());
                                App.CQASingleton.SetIsRunning(false);
                                this.InitCacheQueue(this.ComicId, this.BookId);
                            }
                            else
                            {
                                //foreach (BackgroundTransferRequest btr in BackgroundTransferService.Requests)
                                //{
                                //    UpdateBackgroundTransfer(btr);
                                //}
                                //
                                App.CQASingleton.SetIsRunning(true);
                                BackgroundTransferRequest btr = BackgroundTransferService.Requests.FirstOrDefault<BackgroundTransferRequest>();
                                UpdateBackgroundTransfer(btr);
                            }
                        }
                        else
                        {
                            //下载不正确时，从队列移除或做其它处理
                            RemoveTransferRequest(transfer.RequestId);
                        }
                        break;
                }
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
        }

        private bool RemoveTransferRequest(string transferID)
        {
            // Use Find to retrieve the transfer request with the specified ID.
            BackgroundTransferRequest transferToRemove = BackgroundTransferService.Find(transferID);

            // Try to remove the transfer from the background transfer service.
            try
            {
                if (transferToRemove != null)
                {
                    BackgroundTransferService.Remove(transferToRemove);
                    return true;
                }
                else
                    return false;
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            return false;
        }
        #endregion ******************************下载队列处理******************************



        #region ******************************下载数据******************************
        /// <summary>
        /// 获取章节中的所有图片地址
        /// </summary>
        /// <param name="dbChapter"></param>
        private void GetComicChapterImagesByComicChapter(LDBComicChapter dbChapter)
        {
            this.ComicId = dbChapter.ComicId;
            this.BookId = dbChapter.BookId;
            //
            string requestUrl = string.Concat(KEYS.REQUEST_HOST, string.Format("/comic/comicsread_v3?bookid={0}&partid={1}&partVersion=3", dbChapter.BookId, dbChapter.PartId), "&", KEYS.REQUEST_QUERY_PLATFORM);
            LogHelper.LogInfo(requestUrl, this.GetType(), MethodBase.GetCurrentMethod());
            //

            //
            WebTaskHelper webTask = new WebTaskHelper(new Uri(requestUrl));
            IAsyncResult ia = webTask.BeginWebTask(delegate(IAsyncResult callBackResult)
            {
                try
                {
                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        #region **********获取结果处理**********
                        string result = webTask.EndWebTask(callBackResult);

                        if (string.IsNullOrWhiteSpace(result))
                        {
                            LogHelper.LogError("Result is empty.");
                            //MessageToastManager.Show("未获取到数据！", MessageToastLevel.Error);
                            return;
                        }
                        //
                        if (result.StartsWith("exception:"))
                        {
                            LogHelper.LogError(result);
                            return;
                        }
                        LogHelper.LogInfo(result, this.GetType(), MethodBase.GetCurrentMethod());
                        //

                        var rootCharacterString = JSONHelper.Deserialize<JsonComicContent>(result);
                        if (rootCharacterString != null && !string.IsNullOrWhiteSpace(rootCharacterString.Info))
                        {
                            var saveDbImages = new ObservableCollection<LDBComicChapterImage>();
                            var itemsource = JSONHelper.Deserialize<ObservableCollection<JsonComicContentInfo>>(rootCharacterString.Info);
                            if (itemsource != null && itemsource.Count > 0)
                            {
                                foreach (JsonComicContentInfo jcci in itemsource)
                                {
                                    saveDbImages.Add(new LDBComicChapterImage()
                                    {
                                        ComicId = dbChapter.ComicId,
                                        BookId = dbChapter.BookId,
                                        PartId = dbChapter.PartId,
                                        ImageUrl = jcci.Imgurl,
                                        Referer = jcci.Referer,
                                        ComicIdAndBookIdAndPartId = string.Concat(dbChapter.ComicId, "#", dbChapter.BookId, "#", dbChapter.PartId),
                                        DownloadStatus = ContentDownloadStatus.等待中.ToString()
                                    });
                                }
                            }
                            //漫画的章节中的图片地址列表
                            if (saveDbImages != null && saveDbImages.Count > 0)
                            {
                                App.dbContextHelper.InsertComicChapterImages(saveDbImages);
                                App.CQASingleton.SetIsRunning(false);
                                App.CQASingleton.SetIsLoadNetData(false);
                                this.InitCacheQueue(this.ComicId, this.BookId);
                            }
                        }
                        #endregion **********获取结果处理**********
                    });
                }
                catch (Exception err)
                {
                    LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
                }
            }, webTask);
        }


        #endregion ******************************下载数据******************************
    }
}
